PHP: Stats dashboard
November 14, 2020
<?php
$title = "Dashboard";
require 'includes/header.php';
require 'includes/functions_analytics.php';
require_once 'includes/functions_counters.php'; // We need to reinclude it (in the footer is too late)
?>
<p class="lead mb-5">This dashboard lists all the statistics on the website since it was created. Click on years and months listed on the left to access the detailed data.</p>
<div class="row">
<!-- MENU (left) -->
<div class="col-md-4">
<div class="list-group mb-4">
<?php
for ($year = (int)date('Y'); $year >= (int)date('Y') - 5; $year--): ?>
<a href="?year=<?= $year ?>" class="list-group-item <?= li_active('year', $year) ?>">
<b><?= $year ?></b>
</a><?php
if ( (int)$_GET['year'] === $year ): // List months
if ($_GET['year'] !== date("Y")): $m = 12; else: $m = date('m'); endif;
// If clicked is the current year, then display ONLY past months
for($i=$m;$i>0;$i--): ?>
<a href="?year=<?= $year ?>&month=<?= $i ?>" class="list-group-item <?= li_active('month', $i) ?>">
<?= $breadcrumb[$year][] = date('F',strtotime('01.'.$i.'.2000')); // To list months in letters ?>
</a><?php
endfor;
endif;
endfor; ?>
</div>
</div>
<!-- DATA (right) -->
<div class="col-md-8">
<div class="card mb-3">
<!-- Breadcrumb -->
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<?php $breadcrumb = breadcrumb_dash(); ?>
<li class="breadcrumb-item active"><?= $breadcrumb['total'] ?></li>
<?php if (isset($_GET['year'])): ?>
<li class="breadcrumb-item active"><?= $breadcrumb['year'] ?></li>
<?php endif; ?>
<?php if (isset($_GET['month'])): ?>
<li class="breadcrumb-item active"><?= $breadcrumb['month'] ?></li>
<?php endif; ?>
</ol>
</nav>
<!-- Card (year & month)-->
<div class="card-body">
<?php if (!isset($_GET['year'])): ?>
<div class="row">
<div class="col-sm mb-3">
<h3><?= counter_sum('total'); ?></h3>Visited pages
</div>
<div class="col-sm">
<h3><?= counter_sum(date("Y-m-d")); ?></h3>Today
</div>
</div>
<?php elseif (!isset($_GET['month'])) : ?>
<h3><?= counter_sum('year', $_GET['year']) ?></h3>Visited pages
<?php endif; ?>
<?php if (isset($_GET['month'])): ?>
<h3><?= counter_sum('month', $_GET['year'], $_GET['month']) ?></h3>Visited pages
</div>
</div>
<!-- Table (days) -->
<div class="card">
<table class="table">
<thead class="thead-light">
<tr>
<th>Day</th>
<th>Page views</th>
</tr>
</thead>
<tbody>
<?php if (counter_sum('month', $_GET['year'], $_GET['month']) > 0 ):
for ($i=31; $i>0; $i--):
$day_file = $_GET['year'] . '-' . str_pad($_GET['month'], 2, '0', STR_PAD_LEFT) . '-' . str_pad($i, 2, '0', STR_PAD_LEFT);
if (file_exists(counter_page_views_db($day_file))): ?>
<tr>
<td><?= $i ?></td>
<td><?= counter_page_views_int($day_file); ?></td>
</tr>
<?php endif; ?>
<?php endfor; ?>
<?php else: ?>
<tbody>
<tr>
<td colspan="2">No data</td>
</tr>
</tbody>
<?php endif; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
<?php require 'includes/footer.php'; ?>
</div>
</main><!-- /.container -->
<!-- Footer -->
<footer class="page-footer font-small mt-5">
<!-- Footer Text -->
<div class="container text-center text-md-left py-5">
<div class="row">
<div class="col-md-4">
<h5>Pages list</h5>
<ul class="list-unstyled">
<?= nav_menu(); ?>
</ul>
</div>
<div class="col-md-4">
<h5>Stats</h5>
<ul class="list-unstyled">
<li>
<?php
require_once (dirname(__DIR__) . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'functions_counters.php');
counter_page_views_increment('total');
counter_page_views_increment(date("Y-m-d"));
?>
<!-- // Display counter snipet -->
<b><?= counter_page_views_int('total') ?></b> page view<?php if (counter_page_views_int('total') > 1): ?>s<?php endif; ?>
</li>
</ul>
</div>
<div class="col-md-4">
<h5>Admin</h5>
<ul class="list-unstyled">
<li>
<a href="dashboard.php">Statistics</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js" integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s" crossorigin="anonymous"></script>
</html>
<?php
function li_active(string $period, int $number): string
{
$active = '';
if ((int)$_GET[$period] === $number) {
$active = "active";
}
return $active;
}
function counter_sum(string $period, int $year=2000, int $month=1): int
{
$views = [];
$month = str_pad($month, 2, '0', STR_PAD_LEFT); // To be sure the month are 2 digits in the filename
if($period ==='year') {
$search = "$year-*";
} elseif($period ==='month') {
$search = "$year-$month-*";
} elseif($period === 'total') {
$search = "*-*-*";
} else {
return null;
}
foreach (glob("data/counter_page-views/$search") as $file ) {
$views[] = (int)file_get_contents($file);
}
return (int)array_sum($views);
}
function breadcrumb_dash(): array
{
$breadcrumb['total'] = '5 last years';
$breadcrumb['year'] = $_GET['year'];
$breadcrumb['month'] = date('F',strtotime('01.'.$_GET['month'].'.2000'));
if(isset($_GET['year'])) {
$breadcrumb['total'] = '<a href="dashboard.php">' . $breadcrumb['total'] . '</a>';
}
if(isset($_GET['month'])) {
$breadcrumb['year'] = '<a href="dashboard.php?year=' . $breadcrumb['year'] . '">' . $breadcrumb['year'] . '</a>';
}
return $breadcrumb;
}
<?php
// page views
function counter_page_views_db($file): string
{
$db = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'php-playground' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'counter_page-views' . DIRECTORY_SEPARATOR . $file;
return $db;
}
function counter_page_views_increment($file): void
{
if (strpos($_SERVER["SCRIPT_NAME"], 'dashboard.php') === false) { // Exclude admin pages
$db = counter_page_views_db($file);
if (file_exists($db)) {
$views = (int)file_get_contents($db);
$views++;
} else {
$views = 1;
}
file_put_contents($db, $views);
}
}
function counter_page_views_int($file): int
{
$db = counter_page_views_db($file);
return (int)file_get_contents($db);
}
.page-footer {
background-color: #f3f3f3;
}
a:hover {
text-decoration: none !important;
}
.breadcrumb {
border-radius: .25rem .25rem 0 0;
}
.table thead th {
border: none;
}
tbody > tr:first-child > * {
border-top: none;
}
th {
color: #6c757d !important;
font-weight: 400;
}
@media (min-width: 576px) {
.col-sm:nth-child(2) {
border-left: solid 1px #dddddd !important;
}
}